package it.free.i.virtual.machine.knowledgebase.ciuc.basket;

import it.free.i.virtual.machine.hal.devicealias.command.DeviceAliasPortMessage;
import it.free.i.virtual.machine.hal.devicealias.command.DeviceAliasPortMessagePayload;
import it.free.i.virtual.swarm.ComposableInformationUnit;
import it.free.i.virtual.swarm.ComposableInformationUnitChain;

import java.util.Enumeration;
import java.util.Hashtable;
import java.util.List;

import javax.management.Notification;

import org.apache.log4j.Logger;

/**  
 * Asynchronously takes a notifications list from the notifications list basket and transforms it into a composable information units chain,
 * then remove it from the basket 
 * @author stefano
 */
public class NotificationsListToCiucSwapper implements Runnable {

	private static NotificationsListToCiucSwapper NOTIFICATIONSLIST_TO_CIUCS_SWAPPER_INSTANCE = null;
	private static Logger logger = Logger.getLogger(NotificationsListToCiucSwapper.class);
	private long conversionSleepInterval = 0L;
	
	static{
		NotificationsListToCiucSwapper.getInstance();
	}
	
	/**
	 * Hidden builder for the singleton pattern.
	 * By now it sets the sleep interval to a value This value set will be later in configuration
	 */
	private NotificationsListToCiucSwapper(){
		this.conversionSleepInterval = 1500L;
		Runnable runnable = this;
		Thread thread = new Thread(runnable, "NotificationsListToCiucSwapper-Thread-1500millis-sleep");
		thread.start();
	}
	
	/**
	 * Singleton instance accessor
	 * @return the single instance of this object
	 */
	public static final NotificationsListToCiucSwapper getInstance(){
		
		if(NOTIFICATIONSLIST_TO_CIUCS_SWAPPER_INSTANCE == null){
		   synchronized(NotificationsListToCiucSwapper.class){
			   if(NOTIFICATIONSLIST_TO_CIUCS_SWAPPER_INSTANCE == null){
				  NOTIFICATIONSLIST_TO_CIUCS_SWAPPER_INSTANCE = new NotificationsListToCiucSwapper();
			   }
		   }
		}
		return NOTIFICATIONSLIST_TO_CIUCS_SWAPPER_INSTANCE;
	}
	
	private ComposableInformationUnitChain transform(List<Notification> values){
		
		ComposableInformationUnitChain composableInformationUnitChain = new ComposableInformationUnitChain();
		ComposableInformationUnit composableInformationUnit = null;
		
		Notification notification = null;
		DeviceAliasPortMessage deviceAliasPortMessage = null;
		DeviceAliasPortMessagePayload deviceAliasPortMessagePayload = null;
		
		//Build the ciuc from the data received in the Notifications' list
		
		for(int i= 0; i < values.size(); i++){
			notification = values.get(i);
			deviceAliasPortMessage = (DeviceAliasPortMessage) notification.getUserData();
		
			deviceAliasPortMessagePayload = deviceAliasPortMessage.getPayload();
			logger.debug("Virtual device data payload is of type: [" + deviceAliasPortMessage.getPayloadDataType() + "]");
			composableInformationUnit = deviceAliasPortMessagePayload.getRenderedObjectImage();
			
			composableInformationUnitChain.put(String.valueOf(deviceAliasPortMessage.getCreationTimeStamp()), 
											   composableInformationUnit);
		}
		
		return composableInformationUnitChain;
		
	}

	/**
	 * Run if at least 2 elements are in the fetch-able list, to avoid the need for synchronize 
	 */
	public void run() {
		
		while(true){
			try{
				Thread.sleep(this.conversionSleepInterval);
				Hashtable<String, List<Notification>> allLists = NotificationsListsBasket.getInstance().getNotifications();
				//Take all hashtables where each element has to be rendered, this is the access to all the lists 
				//Now the composable information unitS chain can be added to the beehive
				
				String aKey = null;
				if( (allLists != null) && (!allLists.isEmpty()) ){	
				   Enumeration<String> keys = allLists.keys();
				   while(keys.hasMoreElements()){
					     aKey = keys.nextElement();
					     List<Notification> aList = allLists.get(aKey);
					     ComposableInformationUnitChain composableInformationUnitChain = transform(aList);
					     //Add to the beehive
					     ?? 
				   }
				   
				   
				   
				   NotificationsListsBasket.getInstance().getNotifications().remove(key)
				   
				}
			}catch(InterruptedException iExc){
				   iExc.printStackTrace();
			}
			
			//Going to change
			
		}
		
	}
	
}
